﻿/*
 * @Author Super听歌 qq:841739194
 * @Date 2021/1/25
 * @Version 1.0.0
 * @Description
 * 同步使用：预加载，将lua文件全部缓存在内存当中
 * Lua文件加载 ，使用自定义Loader
 * public delegate byte[] CustomLoader(ref string filepath);
 * public void LuaEnv.AddLoader(CustomLoader loader)
 * 通过AddLoader可以注册个回调，该回调参数是字符串，lua代码里头调用require时，参数将会透传给回调，回调中就可以根据这个参数去加载指定文件，
 * 如果需要支持调试，需要把filepath修改为真实路径传出。该回调返回值是一个byte数组，如果为空表示该loader找不到，否则则为lua文件的内容。
 * 读取Lua脚本，lua脚本加载
 *
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;

public class LuaManager : MonoBehaviour
{
    public List<string> luaFileNames = new List<string>(); //预加载的所有lua文件名称，从ResourceManager中获取
    public XLua.LuaEnv luaEnv;
    private Dictionary<string, byte[]> m_LuaByteScripts; //缓存lua二进制脚本内容

    Action InitOk;

    public void Init(Action _init)
    {
        InitOk += _init;
        luaEnv = new LuaEnv();
        m_LuaByteScripts = new Dictionary<string, byte[]>();
        //luaEnv.AddBuildin();
        luaEnv.AddLoader(Loader);   //自动回调加载lua文件

#if UNITY_EDITOR
        if (AppConst.gameMode == GameMode.EditorMode)
            EditorLoadLuaScript();  //读取lua
        else
            LoadLuaScript();
#endif
    }

    private byte[] Loader(ref string luaName)
    {
        return this.GetLuaByte(luaName);
    }

    //异步
    private void LoadLuaScript()
    {
        foreach (var item in luaFileNames)
        {
            Manager.ResourceManager.LoadLua(item, (UnityEngine.Object obj) =>
            {
                AddLuaScript(item, (obj as TextAsset).bytes); //文本文件资源转换成二进制

                if (m_LuaByteScripts.Count >= luaFileNames.Count)
                {
                    //必需等所有lUa文件加载完成，并且对加载某一个Lua需要一个回调，
                    InitOk?.Invoke();
                    luaFileNames.Clear();
                    luaFileNames = null;
                }
            });
        }
    }


#if UNITY_EDITOR
    /// <summary>
    /// 编辑器下使用的预加载Lua
    /// </summary>
    private void EditorLoadLuaScript()
    {
        //获取所有lua文件名称
        //遍历lua文件，读取内容，并添加到容器当中
        string[] _luaFileNames = Directory.GetFiles(PathUtil.LuaPath, "*.bytes", SearchOption.AllDirectories); //第二个参数：要与文件名匹配的搜索字符串。
        for (int i = 0; i < _luaFileNames.Length; i++)
        {
            string _luaFileName = PathUtil.GetStandardPath(_luaFileNames[i]);
            byte[] _luaBytes = File.ReadAllBytes(_luaFileName); //读取Lua文件的二进制内容
            m_LuaByteScripts[_luaFileName] = _luaBytes;
            //AddLuaScript(_luaFileName, _luaBytes);
        }
    }
#endif


    //内存回收
    private void Update()
    {

        if (luaEnv != null)
        {
            luaEnv.Tick(); //释放资源
        }
    }

    private void OnDestroy()
    {
        if (luaEnv != null)
        {
            luaEnv.Dispose(); //销毁
            luaEnv = null;
        }
    }


    public void AddLuaScript(string assetsName, byte[] luaScript)
    {
        //m_LuaScripts.Add(assetsName, luaScript);
        m_LuaByteScripts[assetsName] = luaScript; //覆盖添加，防止重复
    }

    //启动Lua
    public void StartLua(string name)
    {
        //require某Lua文件,执行文件,一般一个程序就一个
        luaEnv.DoString(string.Format("require '{0}'", name));
    }

    public byte[] GetLuaByte(string luaName)
    {
        //require ui.login.register
        luaName = luaName.Replace(".", "/");
        string luaPath = PathUtil.GetLuaPath(luaName);
        byte[] luaByte = { };
        if (!m_LuaByteScripts.TryGetValue(luaPath, out luaByte)) //判断一下是否已经加载过Lua文件
            Debug.LogError("Lua not Exist :" + luaName);
        return luaByte;
    }

}
